home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- #
- # Apple Macintosh Developer Technical Support
- #
- # BitMap Transformer
- #
- # Transformer.c - C Source
- #
- # Copyright © 1989 Apple Computer, Inc.
- # All rights reserved.
- #
- # Versions:
- # 1.0 10/89
- #
- # Components:
- # MTransformer.p October 1, 1989
- # UTransformer.p October 1, 1989
- # UTransformer.inc1.p October 1, 1989
- # Transformer.c October 1, 1989
- # Transformer.r October 1, 1989
- # Transformer.MAMake October 1, 1989
- # ProjInit October 1, 1989
- # The BitMap Transmogrifier October 1, 1989
- #
- # Requirements:
- # MacApp® 2.0ß9 July 10, 1989
- #
- # "Transformers" is a sample program that demonstrates how to translate,
- # rotate, and scale bitmaps. It uses a MacApp shell to open file, open
- # windows, and handle menus, but the core routine is written in vanilla C.
- #
- ------------------------------------------------------------------------------*/
-
- #include <Types.h>
- #include <QuickDraw.h>
- #include <Files.h>
- #include <Memory.h>
- #include <ToolUtils.h>
- #include <CursorCtl.h>
-
- #define NIL 0L
- #define PI (3.14159265358979323846)
-
-
- //
- // pascal void GetThePicture( short aRefNum, Ptr data );
- //
- // pascal void DoTransform(BitMap *sourceBM, BitMap *destBM, Point center, Point destination,
- // short rotation, extended sx, extended sy);
- //
-
- extern pascal void FailOSErr( short );
- extern pascal void FailNIL( Ptr );
- extern pascal void ClearBitMap( BitMap *aBitMap );
- extern pascal void BusyActivate( Boolean );
-
- pascal void GetThePicture( short aRefNum, Ptr data)
- {
- long srcSize;
- Ptr srcPtr, destPtr, lastDstPtr, saveSrcPtr;
- short scanLine;
-
- FailOSErr(SetFPos(aRefNum, fsFromStart, 512L));
- FailOSErr(GetEOF(aRefNum, &srcSize));
- srcSize = srcSize - 512;
- FailNIL(srcPtr = NewPtr(srcSize));
- FailOSErr(FSRead(aRefNum, &srcSize, srcPtr));
-
- saveSrcPtr = srcPtr;
- destPtr = data;
- lastDstPtr = destPtr;
-
- for ( scanLine = 1; scanLine < 720; scanLine++ ) {
- UnpackBits(&srcPtr, &destPtr, 72);
- };
-
- DisposPtr(saveSrcPtr);
- }
-
- // The following routines that are compiled out are functional, but they are not
- // optimized for speed. They are included here just so that you can see a sample
- // that is a bit clearer than the optimized routine that appears later.
-
- #if false
- Boolean myGetPixel(bm, x, y)
- BitMap *bm;
- short x, y;
- {
- Boolean result;
- Point tempPt;
- long *longPtr;
-
- tempPt.v = y;
- tempPt.h = x;
- if (PtInRect(tempPt, &(bm->bounds))) {
- longPtr = (long *) (bm->baseAddr + ((long)y * bm->rowBytes) + (x / 32) * 4);
- result = 1 & ((*longPtr) >> (31 - (x % 32)));
- } else {
- result = false; /* return white */
- }
- return (result);
- }
-
-
- void mySetPixel(bm, x, y)
- BitMap *bm;
- short x, y;
- {
- Point tempPt;
- long *longPtr;
-
- tempPt.v = y;
- tempPt.h = x;
- if (PtInRect(tempPt, &(bm->bounds))) {
- longPtr = (long *) (bm->baseAddr + ((long)y * bm->rowBytes) + (x / 32) * 4);
- *longPtr |= (0x80000000 >> (x % 32));
- }
- }
-
-
- pascal void DoTransform(BitMap *sourceBM, BitMap *destBM, Point center, Point destination,
- short rotation, extended sx, extended sy)
- {
- short i;
- short j;
- short newX, newY;
- Boolean isSet;
- long *longPtr;
-
- short width = destBM->bounds.right;
- short height = destBM->bounds.bottom;
-
- extended r11 = (1/sx) * cos(rotation * (PI/180));
- extended r12 = -(1/sx) * sin(rotation * (PI/180));
- extended r21 = (1/sy) * sin(rotation * (PI/180));
- extended r22 = (1/sy) * cos(rotation * (PI/180));
-
- extended tx = -destination.h*r11 - destination.v*r12 + center.h;
- extended ty = -destination.h*r21 - destination.v*r22 + center.v;
-
-
- BusyActivate(false);
- Show_Cursor(HIDDEN_CURSOR);
- ClearBitMap(destBM);
-
- for ( j = 0; j < height; j++ ) {
- SpinCursor(4);
- for ( i = 0; i < width; i++ ) {
-
- newX = i*r11 + j*r21 + tx + .5;
- newY = i*r12 + j*r22 + ty + .5;
-
- isSet = myGetPixel(sourceBM, newX, newY);
- if (isSet) mySetPixel(destBM, i, j);
- }
- }
- BusyActivate(true);
- }
- #endif
-
-
- // This version of DoTransform() is optimized for speed. It's not as fast
- // as it could possibly be, but it's fair. Neither is it very readable...
-
- pascal void DoTransform(BitMap *sourceBM, BitMap *destBM, Point center, Point destination,
- short rotation, extended sx, extended sy)
- {
- register short i;
- register short j;
- short newX;
- short newY;
- long *longPtr;
-
- short width = destBM->bounds.right;
- short height = destBM->bounds.bottom;
- Rect *tPtr = &(sourceBM->bounds);
- Ptr sourceBase = sourceBM->baseAddr;
- Ptr destBase = destBM->baseAddr;
- Ptr destBase2;
- short sourceRB = sourceBM->rowBytes;
- short destRB = destBM->rowBytes;
-
- extended rotInRads = rotation * (PI/180);
-
- extended r11 = (1/sx) * cos(rotInRads);
- extended r12 = -(1/sx) * sin(rotInRads);
- extended r21 = (1/sy) * sin(rotInRads);
- extended r22 = (1/sy) * cos(rotInRads);
-
- extended tx = -destination.h*r11 - destination.v*r12 + center.h + .5;
- extended ty = -destination.h*r21 - destination.v*r22 + center.v + .5;
-
- extended interX; /* intermediate result */
- extended interY; /* intermediate result */
-
- BusyActivate(false);
- Show_Cursor(HIDDEN_CURSOR);
- ClearBitMap(destBM);
-
- for ( j = 0; j < height; j++ ) {
- SpinCursor(4); // spin my gears once every 32/4 times through this loop
- destBase2 = destBase + (long) j * destRB;
- interX = j*r12 + tx;
- interY = j*r22 + ty;
- for ( i = 0; i < width; i++ ) {
-
- newX = i*r11 + interX;
- newY = i*r21 + interY;
-
- if ( (newX < tPtr->left) || (newX >= tPtr->right) ||
- (newY < tPtr->top) || (newY >= tPtr->bottom) ) {
- continue;
- } else {
- longPtr = (long *) (sourceBase + ((long)newY * sourceRB) + (newX / 32) * 4);
- if (!(1 & ((*longPtr) >> (31 - (newX % 32)))))
- continue;
- }
-
- longPtr = (long *) (destBase2 + (i / 32) * 4);
- *longPtr |= ( (unsigned long) 0x80000000 >> (i % 32));
- }
- }
- BusyActivate(true);
- }
-
-